#pragma once

#include <ctime>
#include <cstdio>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <stdarg.h>
#include <iostream>
#include <sys/stat.h>
#include <fcntl.h>

const std::string logdir = "log";
const std::string default_filenam = "log.";
const int default_style = 10;
enum
{
    Debug = 0,
    Info,
    Warning,
    Error,
    Fatal,//崩溃
    Unkonw
};

enum
{
    sreen = 10,
    all,
    classfile
};

std::string LvevlToStr(int level)
{
    switch (level)
    {
    case Debug:
        return "Debug";

    case Info:
        return "Info";
    case Warning:
        return "Warning";
    case Error:
        return "Error";

    default:
        return "Unkonw";
    }
}

class Log
{
public:
    Log()
        : style(default_style), filename(default_filenam)
    {
        mkdir(logdir.c_str(), 0775);
    }

    void Eable(int st)
    {
        style=st;
    }
    void WriteLogToOneFile(const std::string &logname, const std::string &info)
    {
        umask(0);
        int fd = open(logname.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0666);
        if (fd < 0)
            return;
        write(fd, info.c_str(), info.size());
        close(fd);
    }

    void WriteLogToClassFile(const std::string &level, const std::string &info)
    {
        std::string logname = logdir;
        logname += "/";
        logname += filename;
        logname += level;

        WriteLogToOneFile(logname, info);
    }

    void WriteLog(std::string &level, std::string &info)
    {
        switch (style)
        {
        case sreen:
            std::cout << info << std::endl;
            break;
        case classfile:
            WriteLogToClassFile(level, info);
            break;
        case all:
            WriteLogToClassFile("all", info);
            break;
        }
    }
    std::string TimeStampExLocalTime()
    {
        time_t currtime = time(nullptr);
        struct tm *curr = localtime(&currtime);

        char time_buff[128];
        snprintf(time_buff, sizeof(time_buff), "%d-%d-%d %d:%d:%d",
                 curr->tm_year + 1900, curr->tm_mon + 1, curr->tm_mday,
                 curr->tm_hour, curr->tm_min, curr->tm_sec);

        return time_buff;
    }

    void LogMessage(int level, const char *format, ...)
    {
        char leftbuffer[1024];
        std::string levelstr = LvevlToStr(level);
        std::string currtime = TimeStampExLocalTime();
        std::string id = std::to_string(getpid());
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%s][%s]",
                 levelstr.c_str(), currtime.c_str(), id.c_str());

        // printf("%s", leftbuffer);

        char rightbuffer[1024];
        va_list args;
        va_start(args, format);
        va_end(args);

        vsnprintf(rightbuffer, sizeof(rightbuffer), format, args);
        std::string logInfo = leftbuffer;
        logInfo += +rightbuffer;

        WriteLog(levelstr, logInfo);
    }

private:
    int style;
    std::string filename;
};


Log lg;